import Abs from '../abyss';
import Ele from '../element';
import Dev from '../develop';
import T from '../unity';

import Cfg from './config';

import {Col, Form, Row, Tabs, Tree} from "antd";
import React from "react";
import {LoadingAlert} from "web";
import WebField from './web-field';

import Image from '../images';

const TreeNode = Tree.TreeNode;
const aiTreeNode = (item = {}) => {
    /*
     * 数据整合处理
     */
    const attrs = {};
    attrs.title = item.text;
    attrs.key = item.key;
    attrs.data = Abs.clone(item.data);

    if (item.children && 0 < item.children.length) {
        return (
            <TreeNode {...attrs}>
                {item.children.map(each => aiTreeNode(each))}
            </TreeNode>
        )
    } else {
        return (<TreeNode {...attrs}/>)
    }
};
const aiTree = (item = {}, rest = {}) => {
    if (Abs.isArray(item)) {
        return (
            <Tree {...rest} className={"web-tree"}>
                {item.map(each => aiTreeNode(each))}
            </Tree>
        )
    } else {
        return (
            <Tree {...rest} className={"web-tree"}>
                {aiTreeNode(item)}
            </Tree>
        )
    }
};

const aiHidden = (reference, values = {}, raft = {}) => {
    if (raft.hidden) {
        return raft.hidden
            .filter(item => Abs.isFunction(item.render))
            .map(each => each.render(values))
    } else return false;
};

const _aiTitle = (reference, cell = {}) => {
    // Fix issue: render is invalid for prop
    const attrs = Abs.clone(cell);
    if (attrs.render) {
        delete attrs.render;
    }
    const {title, ...cellRest} = attrs;
    // Fix issue: list should has `key`
    if (!cellRest.key) cellRest.key = T.randomUUID();
    // 第二种格式出台
    const {config = {}} = cell;
    if (config.description) {
        return (
            <Col {...cellRest} span={24} className={"ux-comment"}>
                <LoadingAlert $alert={config}/>
            </Col>
        )
    } else if (config.tips) {
        const offset = Ele.valueInt(config.offset, 0);
        const span = 24 - offset;
        const attrs = {offset, span};
        if (config.style) {
            attrs.style = config.style;
        }
        return (
            <Col {...attrs} key={cellRest['key']} className={"ux-tips"}>
                {title}
            </Col>
        )
    } else {
        cellRest.className = `ux-title ux-title-pure`
        return (
            <Col {...cellRest} span={24}>
                {title}
            </Col>
        )
    }
}
const _aiSubject = (reference, cell) => {
    const {$subject = {}} = reference.props;
    const attrs = Abs.clone(cell);
    const {subject, ...cellRest} = attrs;
    // Fix issue: list should has `key`
    if (!cellRest.key) cellRest.key = T.randomUUID();
    const data = $subject[subject];
    // 属性处理
    const attrRest = {};
    attrRest.key = cell.key;
    attrRest.className = `ux-subject`;
    attrRest.span = 24;
    return (
        <Col {...attrRest}>
            <img src={Image.ICON_BLOCK[data['uiIcon']]} alt={data.name}/>
            <div className={"ux-subject-tip"}>
                {data.subject}
                &nbsp;&nbsp;
                <div className={"ux-subject-sub"}>
                    {data['nameFull']}
                </div>
            </div>
        </Col>
    )
}
const _aiInput = (reference, values) => (cell = {}) => {
    if (cell.title) {
        // title 渲染
        return _aiTitle(reference, cell);
    } else if (cell.subject) {
        // subject 渲染
        return _aiSubject(reference, cell);
    } else {
        // 其他项
        const {optionItem = {}, optionConfig = {}} = cell;
        const attached = {};
        /*
         * 如果有 rules 则带上 hasFeedback
         * 有 rules 表示有验证规则，则需要设置验证过后的效果
         */
        if (optionConfig.rules && 0 < optionConfig.rules.length) {
            attached.hasFeedback = true;
        }
        /*
         * 检测 __render 值，特殊的验证效果处理
         * 设置特殊的验证效果，主要是非输入型组件的验证效果专用处理
         * 追加 web-form-has-error 类名，保证验证时的提示处理
         * */
        const colAttrs = T.connectItem(cell);
        /*
         * 追加同义词替换，主要用于替换 label 文字描述信息，方便扩展
         */
        const $item = Abs.clone(optionItem);
        {
            /*
             * 双源头同义处理
             * 1. 第一源头来自于表单本身的配置
             * {
             *      "_form":{
             *          "synonym": {}
             *      }
             * }
             * 2. 第二源头来自于属性传入 $synonym
             *
             * 第二源头为编程模式，高优先级
             */
            const {$synonym = {}, config = {}} = reference.props;
            const {synonym = {}} = config.form ? config.form : {};
            const combine = Abs.clone(synonym);
            Object.assign(combine, $synonym);
            if (combine.hasOwnProperty(cell.field)) {
                $item.label = combine[cell.field];
            }
        }
        return (
            <Col {...colAttrs}>
                <Form.Item {...$item} {...attached}>
                    {cell.render ? cell.render(values) : false}
                </Form.Item>
            </Col>
        )
    }
};
const aiField = (reference, values = {}, raft = {}) =>
    (Abs.isArray(raft.rows)) ? raft.rows.map((row) => {
        const {cells = [], ...rest} = row;
        return (
            <Row {...rest}>
                {/* 单元格 */}
                {cells.map(_aiInput(reference, values))}
            </Row>
        )
    }) : false;
const aiInit = (reference, values) => {
    /*
     * 基础初始化
     */
    const {$inited = {}, $record = {}} = reference.props;
    let initials = {};
    if (values && !Abs.isEmpty(values)) {
        initials = Abs.clone(values);
    } else {
        initials = Abs.clone($inited);
    }
    /*
     * 配置初始化
     */
    const {raft = {}} = reference.state;
    let detect = {};
    if (raft.initial) {
        /*
         * 基础解析
         */
        detect = Cfg.initial(reference, raft, $record);
    }
    /*
     * initials 的优先级高于 detect
     */
    Object.assign(detect, initials);
    return Abs.clone(detect);   // 拷贝最终的值
};
/*
 * config 数据结构：
 * {
 *     formKey: 表单的 key（防止修改过后的不按预期的变更）
 * }
 */
const aiForm = (reference, values, configuration = {}) => {
    /*
     * 初始值 initial 优先
     */
    let initials = aiInit(reference, values);
    /*
     * 日志记录
     */
    const {form, config = {}} = reference.props;
    // form 专用属性
    const {raft = {}} = reference.state;
    let attrs = Abs.clone(raft.form);
    if (!attrs) attrs = {};
    if (configuration['formKey']) {
        attrs.key = configuration['formKey'];
    }
    // form 中的 className
    if (configuration.className) {
        attrs.className = `web-form ${configuration.className}`;
    } else {
        const configForm = config.form ? config.form : {};
        if (configForm.className) {
            if (0 < configForm.className.indexOf('web-form')) {
                attrs.className = configForm.className;
            } else {
                attrs.className = `web-form ${configForm.className}`;
            }
        } else {
            attrs.className = `web-form`;
        }
    }

    const touched = form.isFieldsTouched();
    if (!touched) {
        const options = raft.options ? raft.options : {};
        if (Abs.isNotEmpty(initials)) {
            Dev.dgDebug(initials, "初始化表单数据：" + options.id, "#8B5A00");
        }
    }
    return (
        <Form {...attrs}>
            {/** 隐藏组件 hidden **/}
            {aiHidden(reference, initials, raft)}
            {/** 字段渲染 **/}
            {aiField(reference, initials, raft)}
        </Form>
    )
};
const aiFormInput = (reference, values, raft = {}) => {
    /*
     * 初始值 initial 优先
     */
    let initials = aiInit(reference, values);
    const {form = {}} = raft;
    return (
        <div className={form.className}>
            {/** 隐藏组件 hidden **/}
            {aiHidden(reference, initials, raft)}
            {/** 字段渲染 **/}
            {aiField(reference, initials, raft)}
        </div>
    )
};
const aiFormField = (reference, fieldConfig = {}, fnJsx) => {
    const {form} = reference.props;
    if (fieldConfig) {
        let fnRender;
        if (Abs.isFunction(fnJsx)) {
            fnRender = fnJsx;
        } else {
            if (fieldConfig.render) {
                fnRender = WebField[fieldConfig.render];
            } else {
                fnRender = WebField.aiInput;
            }
        }
        const {
            optionItem,
            optionConfig,
            optionJsx,
            field,
        } = fieldConfig;
        const {getFieldDecorator} = form;
        return (
            <Form.Item {...optionItem}>
                {getFieldDecorator(field, optionConfig)(fnRender(reference, optionJsx))}
            </Form.Item>
        )
    } else {
        return false;
    }
}
// ---------------- O.tab.js
const aiTabPage = (reference, children = {}) => {
    const {$tabs = {}} = reference.state ?
        reference.state : {};
    const {items = [], ...rest} = $tabs;
    return (
        <Tabs {...rest}>
            {items.map(item => {
                const fnRender = children[item.key];
                return (
                    <Tabs.TabPane {...item}>
                        {Abs.isFunction(fnRender) ? fnRender(item) :
                            `对不起，children 函数丢失：${item.key}`}
                    </Tabs.TabPane>
                )
            })}
        </Tabs>
    )
}
// eslint-disable-next-line import/no-anonymous-default-export
export default {
    aiTabPage,
    aiTree,
    aiForm,
    aiInit, // 统一处理
    aiField,
    aiFormInput,
    aiFormField,
}